﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using DynamicLinqExtensions.Exceptions;

namespace DynamicLinqExtensions
{
    public static class GeneralExtensions
    {
        public static Type GetTypeFromIQueryable(this IQueryable queryable)
        {
            var genericArguments = queryable.GetType().GetGenericArguments();
            if (!genericArguments.Any())
                throw new DynamicLinqExtensionsException("Could not determine the Type of queryable being passed in as IQueryable");
            return genericArguments[0];
        }
        
        public static PropertyInfo GetPropertyInfo(this IQueryable queryable, string propertyName)
        {
            var type = queryable.GetTypeFromIQueryable();
            var propertyInfo = type.GetProperties().SingleOrDefault(x => x.Name == propertyName);
            if (propertyInfo == null)
                throw new DynamicLinqExtensionsException("Could not find property " + propertyName + " in type " + type.Name);
            return propertyInfo;
        }

        public static dynamic Single(this IQueryable queryable)
        {
            dynamic result = null;
            var count = 0;
            foreach (var item in queryable)
            {
                count += 1;
                result = item;
            }
            if (count>1)
                throw new DynamicLinqExtensionsException("Sequence contains more than one element.");
            if (count==0)
                throw new DynamicLinqExtensionsException("Sequence contains no elements.");
            return result;
        }

        public static dynamic First(this IQueryable queryable)
        {
            return Enumerable.Cast<object>(queryable).FirstOrDefault();
        }

        public static int Count(this IQueryable queryable)
        {
            var result = 0;
            foreach (var item in queryable)
            {
                result += 1;
            }
            return result;
        }
    }
}
